package list.impl;

import iterator.MyIterator;
import iterator.impl.MyLinkedListIterator;
import list.MyList;

public class MyLinkedList<T> implements MyList<T> {

    private Node<T> head;

    private Node<T> last;

    private int size;

    public MyLinkedList() {
        size = 0;
    }

    public Node<T> getHead() {
        return head;
    }

    @Override
    public MyIterator<T> iterator() {
        return new MyLinkedListIterator<>(this);
    }

    /**
     * 尾插法
     */
    @Override
    public boolean add(T o) {
        Node<T> pre = last;
        Node<T> node = new Node<>(pre, null, o);
        last = node;
        if (pre == null) {
            head = node;
        } else {
            pre.next = node;
        }
        size++;
        return true;
    }

    @Override
    public int size() {
        return this.size;
    }

    @Override
    public boolean isEmpty() {
        return this.size() <= 0;
    }

    @Override
    public boolean remove(int index) {
        if (index >= this.size) throw new IndexOutOfBoundsException("下标越界");
        if (index == this.size - 1) {
            Node<T> l = last;
            last = l.pre;
            last.next = null;
            l.pre = null;
            return true;
        }
        Node<T> current = head;
        int currentIndex = 0;
        while (current != null) {
            if (currentIndex == index) {
                Node<T> pre = current.pre;
                Node<T> next = current.next;
                pre.next = next;
                next.pre = pre;
                current.pre = null;
                current.next = null;
                break;
            }
            current = current.next;
            currentIndex++;
        }
        this.size--;
        return true;
    }

    @Override
    public T get(int index) {
        if (index >= this.size) throw new IndexOutOfBoundsException("下标越界");
        Node<T> current = head;
        int currentIndex = 0;
        while (current != null) {
            if (currentIndex == index) {
                return current.value;
            }
            current = current.next;
            currentIndex++;
        }
        return null;
    }

    public Node<T> getLast() {
        return this.last;
    }

    public static class Node<T> {

        public Node<T> pre;

        public Node<T> next;

        private T value;

        public Node(Node<T> pre, Node<T> next, T value) {
            this.pre = pre;
            this.next = next;
            this.value = value;
        }

        public T getValue() {
            return value;
        }

    }
}
